package fem2.mesh_and_topology;

import math2.MathUtilities;

/**
 * spatial criteria for sphere and circle
 * 
 * @author hbui
 * 
 */
public class SphereSpatialCriteria extends SpatialCriteria {

	private double[] x0;
	private double r;

	public SphereSpatialCriteria(double x0, double y0, double r) {
		this.x0 = new double[] { x0, y0 };
		this.r = r;
	}

	public SphereSpatialCriteria(double x0, double y0, double z0, double r) {
		this.x0 = new double[] { x0, y0, z0 };
		this.r = r;
	}

	@Override
	public boolean isSatisfied(double... x) {
		int dim = x0.length;
		if (dim == 2) {
			return Math.sqrt(Math.pow(x[0] - x0[0], 2) + Math.pow(x[1] - x0[1], 2)) - r < MathUtilities.tol6;
		} else if (dim == 3) {
			return Math.sqrt(Math.pow(x[0] - x0[0], 2) + Math.pow(x[1] - x0[1], 2)
					+ Math.pow(x[2] - x0[2], 2))
					- r < MathUtilities.tol6;

		} else {
			throw new Error("invalid dimension");
		}
	}

	@Override
	public boolean isIntersected(double x0, double y0, double size) {

		double halfSize = size / 2;
		double dx = Math.abs(this.x0[0] - (x0 + halfSize));
		double dy = Math.abs(this.x0[1] - (y0 + halfSize));

		if (dx >= (r + halfSize)) {
			return false;
		}
		if (dy >= (r + halfSize)) {
			return false;
		}

		if (dx < halfSize) {
			return true;
		}
		if (dy < halfSize) {
			return true;
		}

		double cornerDIstance = Math.sqrt(Math.pow(dx - halfSize, 2) + Math.pow(dy - halfSize, 2));
		return cornerDIstance < r;
	}

	@Override
	public boolean isIntersected(double x0, double y0, double z0, double size) {

		double halfSize = size / 2;
		double dx = Math.abs(this.x0[0] - (x0 + halfSize));
		double dy = Math.abs(this.x0[1] - (y0 + halfSize));
		double dz = Math.abs(this.x0[2] - (z0 + halfSize));

		if (dx >= (r + halfSize)) {
			return false;
		}
		if (dy >= (r + halfSize)) {
			return false;
		}
		if (dz >= (r + halfSize)) {
			return false;
		}

		if (dx < halfSize) {
			return true;
		}
		if (dy < halfSize) {
			return true;
		}
		if (dz < halfSize) {
			return true;
		}

		double cornerDIstance = Math.sqrt(Math.pow(dx - halfSize, 2) + Math.pow(dy - halfSize, 2)
				+ Math.pow(dz - halfSize, 2));
		return cornerDIstance < r;
	}
}
